package com.justgame.project.base.interceptor;

import com.justgame.project.base.annotation.ProtectAccess;
import com.justgame.project.cloud.common.constant.Const;
import com.justgame.project.cloud.common.exception.Exc;
import com.justgame.project.cloud.common.util.RedisUtil;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Feign 接口保护过滤器
 * @author ZhouWeiBo
 * @create 2022/4/18
 */
@Component
@AllArgsConstructor
public class FeignApiProtectInterceptor implements HandlerInterceptor {

    private final RedisUtil redisUtil;

    private boolean isInternalFeignRequest(HttpServletRequest request){
        try{
            /* 取出请求头中的参数 */
            String authCode = request.getHeader(Const.FEIGN_REQUEST_HEADER_AUTH),
                    feignAppName = request.getHeader(Const.FEIGN_REQUEST_HEADER_APP_NAME);
            if (StringUtils.isBlank(authCode) || StringUtils.isBlank(feignAppName)) {
                return false;
            }
            /* 比对是否存在 */
            String redisKey = String.format("%s%s",Const.FEIGN_REQUEST_REDIS_AUTH,authCode);
            String realAppName = redisUtil.get(redisKey);
            /* 比对结果 */
            if (realAppName == null || !realAppName.equals(feignAppName)) {
                throw new Exc(Const.NOT_FEIGN_REQUEST_MSG);
            }
            redisUtil.delete(redisKey);
            return true;
        }catch (NullPointerException e){
            throw new Exc(Const.NOT_FEIGN_REQUEST_MSG);
        }
    }


    @SneakyThrows
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (handler instanceof HandlerMethod) {
            return isInternalFeignRequest(request);
        }
        return true;
    }
}
